package com.bomberdroid.ui;

import java.util.ArrayList;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

import com.bomberdroid.model.Objet;
import com.bomberdroid.model.Player;
import com.bomberdroid.protocols.ConnectedThread;
import com.bomberdroid.protocols.Connexion;
import com.bomberdroid.protocols.DataSharing;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;

public class ServerGame extends Activity {
	
	private Connexion connexion;
	private ArrayList<ConnectedThread> clients = new ArrayList<ConnectedThread>();
	private int mapId;
	
	// Handler to manage communications from clients
	private Handler.Callback c = new Handler.Callback() {
		public boolean handleMessage(Message msg) {
			return handleCommunication(msg);
		}
	};
	private Handler handler = new Handler(c);
	
	// Timer for sending data throught socket
	private Timer timer = new Timer();
	private int tickCount = 0;
	private TimerTask task = new TimerTask() {
		@Override public void run() {
			if(!end){
				checkEndGame();
				send();
			}
			else if(tickCount >= endTick){
				finish();
			}
			tickCount++;
		}
	};
	
	private GamePanel gamePanel;
	private Player[] players;
	private static int nbDead = 0;
	
	private boolean end = false;
	private int endTick = 0;
	private String endMessage = "";
	
	@Override protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		DataSharing.message = "";
		nbDead = 0;
		Objet.endGame = false;
		
		this.clients = DataSharing.Server_clients;
		for(ConnectedThread client : this.clients){
			client.setHandler(this.handler);
			client.flush();
		}
		this.connexion = DataSharing.Server_connexion;
		this.mapId = DataSharing.Server_map;
		
		this.gamePanel = new GamePanel(this, this.mapId, true);
		this.setContentView(this.gamePanel);
		
		this.initGame();
		
		this.timer.schedule(task, 0, 50);
	}
	
	/**	Will init the game with the clients data */
	private void initGame(){
		this.players = new Player[this.clients.size()+1];
		this.players[0] = this.gamePanel.getMap().getListeJ()[0];
		this.players[0].setNom(this.connexion.getIdentity());
		for(int i=1; i < this.clients.size()+1 ; i++){
			this.players[i] = this.gamePanel.getMap().getListeJ()[i];
			this.players[i].setNom(this.clients.get(i-1).getIdentity());
			this.players[i].setIndice(i);
		}
		this.gamePanel.getMap().setListeJ(this.players);
	}
	
	public static void incNbDead(){
		nbDead++;
	}
	
	private void checkEndGame(){
		if(nbDead >= this.players.length -1 ){
			this.gamePanel.getControls().setEndGame(true);
			Objet.endGame = true;
			this.end = true;
			this.endTick = tickCount+60;
			Player winner = null;
			for(Player p : this.players){
				if(!p.isMort())
					winner = p;
			}
			this.endMessage = (winner != null ? "Winner :\n"+winner.getNom() : "Game is draw !");
			this.runOnUiThread(new Runnable() {public void run() {
				Toast.makeText(getBaseContext(), endMessage, Toast.LENGTH_LONG).show();
			}});
		}
	}
	
	/** Remove the client that disconnected */
	private void removeClient(String identity){
		ConnectedThread leavingClient = null;
		for (ConnectedThread client : this.clients) {
				if(client.getIdentity().equals(identity))
					leavingClient = client;
		}
		if(leavingClient == null){
			Log.d("Communication", "Error : Client "+identity+" not found");
			return;
		}
		leavingClient.cancel();
		this.clients.remove(leavingClient);
		
		
		for(int i = 0; i < this.players.length ; i++){
			if(this.players[i].getNom().equals(identity)){
				this.players[i].setMort(true);
				DataSharing.message += "7;"+i+"&8;"+identity+"&";
				break;
			}
		}
	}
	
	/** Handles messages from clients comming through ConnectedThread and the Handler
	 * 
	 * @param msg
	 * @return
	 */
	private boolean handleCommunication(Message msg){
		boolean res = true;
		String s = new String((byte[])msg.obj, 0, msg.arg1);
		Log.d("Communication", "ServerGame received : "+s);
		String[] messages = s.split("&");
		for(String mess : messages){
			String[] data = mess.split(";");
			if(data[0].equals("0")){
				this.removeClient(data[1]);
			}
			else if(data[0].equals("1")){
				DataSharing.message += mess+"&";
				this.gamePanel.getMap().getPlayer(Integer.parseInt(data[1])).updateState(Integer.parseInt(data[2]));
			}
			else if(data[0].equals("2")){
				DataSharing.message += mess+"&";
				this.gamePanel.getMap().getPlayer(Integer.parseInt(data[1])).updateState(Player.ZERO);
			}
			else if(data[0].equals("3")){
				this.gamePanel.getMap().getPlayer(Integer.parseInt(data[1])).setControl(Player.POSER, new Date());
			}
			else if(data[0].equals("4")){
				this.gamePanel.getMap().getPlayer(Integer.parseInt(data[1])).setControl(Player.POSER, null);
			}
			else{
				res = false;
			}
		}
		return res;
	}
	
	/** Send the message in DataSharing to all clients */
	private void send(){
		String mess = DataSharing.message;
		DataSharing.message = "";
		if(this.tickCount % 10 == 0){
			for(Player p : this.players)
				mess += "2;"+p.getIndice()+";"+p.getX()+";"+p.getY()+"&";
		}
		if(!mess.equals("")){
			for(ConnectedThread client : this.clients){
				try{client.write(mess);}catch(Exception e){client.cancel();this.clients.remove(client);}
			}
		}
	}

	@Override protected void onDestroy() {
		Log.d("Communication", "ServerGame : Destroying");
		//this.gamePanel.surfaceDestroyed(this.gamePanel.getHolder());
		this.gamePanel = null;
		if(!this.task.cancel())
			Log.d("Communication", "ServerGame : Enable to stop task");
		this.task = null;
		this.timer.cancel();
		this.timer = null;
		if(!this.end){
			for (ConnectedThread client : this.clients) {
				try {client.write("0");} catch (Exception e) {e.printStackTrace();}
			}
		}
		DataSharing.message = "";
		super.onDestroy();
	}
}
